﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using DBAccessLibrary.Common;
using System.Xml.Serialization;

namespace DBAccessLibrary.Model
{
    /// <summary>
    /// 数据库地址
    /// </summary>
    [Serializable]
    public class ServerEntity : DataBaseEntity
    {
        public ServerEntity(string name):base(name)
        {
            ImageUrl = "/Images/Tree/server.png";
        }

        public override DataBaseEntity Copy()
        {
            ServerEntity entity = new ServerEntity(Name)
                                      {
                                          IsExpanded = this.IsExpanded, IsSelected = this.IsSelected
                                      };
            Copy(entity);
            if (this.ChildNodes.Count > 0)
            {
                foreach (DataBaseEntity db in this.ChildNodes.ToArray())
                {
                    DataBaseEntity baseEntity = db.Copy();
                    if (baseEntity != null)
                    {
                        entity.ChildNodes.Add(db.Copy());
                    }
                }
                return entity;
            }
            return null;
        }
    }

    /// <summary>
    /// 数据库
    /// </summary>
     [Serializable]
    public class DBEntity : DataBaseEntity
    {
        private DBConnectStatus _status = DBConnectStatus.Off;
        private ConnectionModel _connectionSource;
        public DBEntity(string name)
            : base(name)
        {
            ImageUrl = "/Images/Tree/db.png";
        }
        public DBConnectStatus Status
        {
            get { return _status; }
            set
            {

                _status = value;
                ChangeIcon();
                this.NotifyPropertyChanged(o => o.Status);
            }
        }

        public ConnectionModel ConnectionSource
        {
            get { return _connectionSource; }
            set
            {
                if (value != _connectionSource)
                {
                    _connectionSource = value;
                    this.NotifyPropertyChanged(o => o.ConnectionSource);
                }
            }
        }

        private void ChangeIcon()
        {
            if (_status == DBConnectStatus.Connected)
            { 
                ImageUrl = "/Images/Tree/btnConnect.png";
                SysCache.DBConnection = _connectionSource;
               
                if (this.ChildNodes.Count > 0)
                {
                    SysCache.TableList = ChildNodes[0].ChildNodes.Cast<TableEntity>();
                    SysCache.ViewList = ChildNodes[1].ChildNodes.Cast<ViewEntity>();
                    SysCache.ProcList = ChildNodes[2].ChildNodes.Cast<ProcEntity>();
                }
            }
            else
            {
                ImageUrl = "/Images/Tree/btnUnConnect.png";
                SysCache.DBConnection = null;
                SysCache.TableList = null;
                SysCache.ViewList = null;
                SysCache.ProcList = null;
                SysCache.TypeList = null;
            }
        }

        /// <summary>
        /// 撤销状态
        /// </summary>
        public override void ClearState()
         {
             if (SysCache.DBConnection != this.ConnectionSource)
             {
                 foreach (DataBaseEntity entity in this.ChildNodes.ToArray())
                 {
                     this.ChildNodes.Remove(entity);
                 }
             }
             else
             {
                 base.ClearState();
             }
         }

        public override DataBaseEntity Copy()
        {
            DBEntity entity = new DBEntity(Name)
                                  {
                                      ConnectionSource = this.ConnectionSource,
                                      IsExpanded = this.IsExpanded,
                                      IsSelected = this.IsSelected
                                  };
            Copy(entity);
            entity.ImageUrl = "/Images/Tree/btnUnConnect.png";
            return entity;
        }

    }

     /// <summary>
     /// 表信息描述
     /// </summary>
     [Serializable]
     public class TableInfoEntity : DataBaseEntity
     {
         public TableInfoEntity(string name)
            : base(name)
        {
        }
         public override DataBaseEntity Copy()
         {
             TableInfoEntity entity = new TableInfoEntity(Name);
             Copy(entity);
             if (this.ChildNodes.Count > 0)
             {
                 foreach (DataBaseEntity db in this.ChildNodes.ToArray())
                 {
                     DataBaseEntity baseEntity = db.Copy();
                     if (baseEntity != null)
                     {
                         entity.ChildNodes.Add(db.Copy());
                     }
                 }
             }
             return entity;
         }
         public string TableName { get; set; }
        
     }

    /// <summary>
    /// 表
    /// </summary>
     [Serializable]
    public class TableEntity : DataBaseEntity
    {
         public TableEntity(string name):base(name)
         {
             ImageUrl = "/Images/Tree/table.png";
         }

         /// <summary>
         /// 主键的名称
         /// </summary>
         public string PrimaryKeyName { get; set; }

         /// <summary>
         /// 查询所有记录
         /// </summary>
         /// <returns></returns>
         public string SelectAll()
         {
             return DBOperatorFactory.GetGrammar(SysCache.DBConnection).SelectAll(this);
         }

         /// <summary>
         /// 查询前100条记录
         /// </summary>
         /// <returns></returns>
         public string SelectTop()
         {
             if (SysCache.DBConnection != null)
             {
                 return DBOperatorFactory.GetGrammar(SysCache.DBConnection).SelectTop(this, 100);
             }
             return string.Empty;
         }

         public IEnumerable<FieldEntity> FileNodes 
         {
             get
             {
                 return ChildNodes[0].ChildNodes.Cast<FieldEntity>();
             }
         }
         public void Add(FieldEntity entity)
         {
             if (entity == null)
                 return;
             ChildNodes[0].ChildNodes.Add(entity);
         }
         public void Remove(FieldEntity entity)
         {
             if (entity == null)
                 return;
             ChildNodes[0].ChildNodes.Remove(entity);
         }

         public IEnumerable<RelationshipEntity> RelationNodes
         {
             get { return ChildNodes[1].ChildNodes.Cast<RelationshipEntity>(); }
         }

         public IEnumerable<IndexDescriptionEntity> IndexNodes
         {
             get
             {
                 return ChildNodes[2].ChildNodes.Cast<IndexDescriptionEntity>();
             }
         }

         public override DataBaseEntity Copy()
         {
             TableEntity entity = new TableEntity(Name);
             Copy(entity);
             if (this.ChildNodes.Count > 0)
             {
                 foreach (DataBaseEntity db in this.ChildNodes)
                 {
                     DataBaseEntity baseEntity = db.Copy();
                     if (baseEntity != null)
                     {
                         entity.ChildNodes.Add(db.Copy());
                     }
                 }
             }
             return entity;
         }

         public IEnumerable<string> AddPrimarySql
         {
             get
             {
                 return DBOperatorFactory.GetGrammar(SysCache.DBConnection).EditPrimary(this);
             }
         }

         public void Commit()
         {
             foreach (FieldEntity entity in FileNodes)
             {
                 entity.Commit();
             }
         }
         public void RollBack()
         {
             foreach (FieldEntity entity in FileNodes)
             {
                 entity.RollBack();
             }
         }
    }
     
    [Serializable]
    public class FieldEntity : DataBaseEntity
    {
        public FieldEntity():base(string.Empty)
        {
            ImageUrl = "/Images/Tree/field.png";
        }

        public FieldEntity(string name)
            : base(name)
        {
            ImageUrl = "/Images/Tree/field.png";
        }

        private bool _isPrimaryKey;
        private bool _isForeignKey;
        private string _tableName =string.Empty;
        private string _typeName =string.Empty;
        private string _length = string.Empty;
        private string _scale=string.Empty;
        private bool _isNull;
        private int _index;
        private string _defaultValue=string.Empty;

        public bool IsPrimaryKey
        {
            get { return _isPrimaryKey; }
            set
            {
                if (value != _isPrimaryKey)
                {
                    this.Change(o=>o.IsPrimaryKey,value);
                }
                _isPrimaryKey = value;
                ChangeIcon();
                this.NotifyPropertyChanged(o => o.IsPrimaryKey);
            }
        }
        public bool IsForeignKey
        {
            get { return _isForeignKey; }
            set
            {
                _isForeignKey = value;
                ChangeIcon();
                this.NotifyPropertyChanged(o => o._isForeignKey);
            }
        }

        public string TableName {
            get { return _tableName; }
            set 
            {
                if (value != _tableName)
                {
                    if (value == null)
                        value = string.Empty;
                    this.Change(o => o.TableName, value);
                    _tableName = value;
                }
            }
        }

        public string ColumnName
        {
            get { return this.Name; }
            set
            {
                if (value != Name)
                {
                    this.Change(o => o.ColumnName, value);
                    Name = value;
                }
            }
        }
        /// <summary>
        /// 类型名称
        /// </summary>
        public string TypeName
        {
            get { return _typeName; }
            set 
            {
                if (value != _typeName)
                {
                    if (value == null)
                        value = string.Empty;
                    this.Change(o => o.TypeName, value);
                    _typeName = value;
                }
            } 
        }
        /// <summary>
        /// 长度
        /// </summary>
        public string Length  
        {
            get { return _length; }
            set 
            {
                if (value != _length)
                {
                    if (value == null)
                        value = string.Empty;
                    this.Change(o => o.Length, value);
                    _length = value;
                }
            } 
        }
        /// <summary>
        /// 小数位
        /// </summary>
        public string Scale 
        {
            get { return _scale; }
            set 
            {
                if (value != _scale)
                {
                    if (value == null)
                        value = string.Empty;
                    this.Change(o => o.Scale, value);
                    _scale = value;
                }
            } 
        }
        /// <summary>
        /// 是否可空
        /// </summary>
        public bool IsNull
        {
            get { return _isNull; }
            set 
            {
                if (value != _isNull)
                {
                    this.Change(o => o.IsNull, value);
                    _isNull = value;
                }
            } 
        }
        /// <summary>
        /// 建表时的顺序
        /// </summary>
        public int Index  
        {
            get { return _index; }
            set 
            {
                if (value != _index)
                {
                    this.Change(o => o.Index, value);
                    _index = value;
                }
            } 
        }
        /// <summary>
        /// 默认值
        /// </summary>
        public string DefaultValue  
        {
            get { return _defaultValue; }
            set 
            {
                if (value != _defaultValue)
                {
                    if (value == null)
                        value = string.Empty;
                    this.Change(o => o.DefaultValue, value);
                    _defaultValue = value;
                }
            } 
        }

        public string LengthString
        {
            get 
            {
                string str = Length;
                if (!string.IsNullOrWhiteSpace(Scale) && Scale.Trim() != "0")
                {
                    str += "," + Scale;
                }
                if (str == string.Empty)
                    return string.Empty;
                return str;
            }
            set
            {
                if (value != null && value != LengthString)
                {
                    this.Change(o => o.LengthString, value);
                    string[] data = value.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries);
                    if (data.Length == 1)
                        Length = data[0];
                    else
                    {
                        Length = data[0];
                        Scale = data[1];
                    }
                }

            }
        }
        private void ChangeIcon()
        {
            if (IsPrimaryKey)
            {
                ImageUrl = "/Images/Tree/primarykey.png";
            }
            else if (IsForeignKey)
            {
                ImageUrl = "/Images/Tree/foreignkey.png";
            }
            else
            {
                ImageUrl = "/Images/Tree/field.png";
            }
        }

        public string AddColumnSql
        {
            get { return DBOperatorFactory.GetGrammar(SysCache.DBConnection).AddColumn(this); }
        }
        public IEnumerable<string> RemoveColumnSql
        {
            get { return DBOperatorFactory.GetGrammar(SysCache.DBConnection).RemoveColumn(this); }
        }

        public void SetEntity(FieldEntity entity)
        {
            TableName = entity.TableName;
            IsForeignKey = entity.IsForeignKey;
            IsPrimaryKey = entity.IsPrimaryKey;
            TypeName = entity.TypeName;
            Length = entity.Length;
            Scale = entity.Scale;
            IsNull = entity.IsNull;
            Index = entity.Index;
            DefaultValue = entity.DefaultValue;

        }
       

        public override DataBaseEntity Copy()
        {
            FieldEntity entity = new FieldEntity(Name)
                                     {
                                         TableName=this.TableName,
                                         IsForeignKey=this.IsForeignKey,
                                         IsPrimaryKey = this.IsPrimaryKey,
                                         TypeName = this.TypeName,
                                         Length = this.Length,
                                         Scale = this.Scale,
                                         IsNull = this.IsNull,
                                         Index=this.Index,
                                         DefaultValue=this.DefaultValue
                                     };

            Copy(entity);
           
            return entity;
        }

        public override bool Equals(object obj)
        {
            FieldEntity newEntity = obj as FieldEntity;
            if (newEntity == null)
                return this == obj;

            if(newEntity.TableName == this.TableName &&
                newEntity.Name == this.Name &&
                newEntity.IsPrimaryKey == this.IsPrimaryKey &&
                newEntity.IsForeignKey == this.IsForeignKey &&
                newEntity.IsNull == this.IsNull &&
                newEntity.TypeName == this.TypeName &&
                newEntity.Length == this.Length &&
                newEntity.Scale == this.Scale &&
                newEntity.Index == this.Index &&
                newEntity.DefaultValue == this.DefaultValue)
            {
                return true;
            }
            return false;

        }

        public override int GetHashCode()
        {
            return this.TableName.GetHashCode() ^
                   this.Name.GetHashCode() ^
                   this.IsPrimaryKey.GetHashCode() ^
                   this.IsForeignKey.GetHashCode() ^
                   this.IsNull.GetHashCode() ^
                   this.TypeName.GetHashCode() ^
                   this.Scale.GetHashCode() ^
                   this.Index.GetHashCode() ^
                   this.DefaultValue.GetHashCode();
        }

        public EditStatus Status
        { get; set; }

        internal bool _isBackup;
        internal Dictionary<string,object> _changeDic;
        public void BackUp()
        {
            _changeDic = new Dictionary<string, object>();
            _isBackup = true;
        }
        public void RollBack()
        {
            _isBackup = false;
            if (_changeDic != null)
            {
                foreach (string key in _changeDic.Keys)
                {
                    this.GetType().GetProperty(key).SetValue(this, _changeDic[key], null);
                }
            }
            this.Status = EditStatus.UnChange;
            BackUp();
        }
        public void Commit()
        {
            _isBackup = false;
            this.Status = EditStatus.UnChange;
            BackUp();
        }
    }
    public static class FieldEntityEx
    {
        /// <summary>
        /// 查看某字段是否已改变
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="entity"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public static bool IsChange<T, TProperty>(this T entity, Expression<Func<T, TProperty>> func) where T : FieldEntity
        {
            MemberExpression member = func.Body as MemberExpression;
            if (null != member)
            {
                string memberName = member.Member.Name;
                object obj = entity.GetType().GetProperty(memberName).GetValue(entity, null);
                if (entity._changeDic.ContainsKey(memberName))
                {
                    return obj != entity._changeDic[memberName];
                }
            }
            return false;
        }
        public static bool IsChange<T>(this T entity, string protecName) where T : FieldEntity
        {
            if (!string.IsNullOrEmpty(protecName))
            {
                try
                {
                    object obj = entity.GetType().GetProperty(protecName).GetValue(entity, null);
                    if (entity._changeDic.ContainsKey(protecName))
                    {
                        return obj != entity._changeDic[protecName];
                    }
                }
                catch{}
            }
            return false;
        }

        /// <summary>
        /// 获取没有改变的值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="entity"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public static object GetNoChangeValue<T, TProperty>(this T entity, Expression<Func<T, TProperty>> func) where T : FieldEntity
        {
             MemberExpression member = func.Body as MemberExpression;
            if (null != member)
            {
                string memberName = member.Member.Name;
                if (entity._changeDic.ContainsKey(memberName))
                {
                    return entity._changeDic[memberName];
                }
            }
            return null;
        }
        internal static void Change<T, TProperty>(this T entity, Expression<Func<T, TProperty>> func,object newValue) where T : FieldEntity
        {
             MemberExpression member = func.Body as MemberExpression;
             if (null != member)
             {
                 if (entity._isBackup)
                 {
                     if (entity.Status == EditStatus.UnChange)
                     {
                         object obj = entity.GetType().GetProperty(member.Member.Name).GetValue(entity, null);
                         entity.Status = EditStatus.Modify;
                         entity._changeDic.Add(member.Member.Name, obj);
                     }
                     else
                     {
                         if (entity._changeDic.ContainsKey(member.Member.Name))
                         {
                             if (newValue.Equals(entity._changeDic[member.Member.Name]))
                                 entity._changeDic.Remove(member.Member.Name);
                             if (entity._changeDic.Count == 0)
                                 entity.Status = EditStatus.UnChange;
                         }
                         else
                         {
                             object obj = entity.GetType().GetProperty(member.Member.Name).GetValue(entity, null);
                             entity._changeDic.Add(member.Member.Name, obj);
                         }
                     }

                 }
             }
        }
    }



    /// <summary>
    /// 索引实体
    /// </summary>
    [Serializable]
    public class IndexEntity : DataBaseEntity
    {
        public IndexEntity(string name)
            : base(name)
        {
        }


        /// <summary>
        /// 排序（ASC 升序  DESC 降序）
        /// </summary>
        public string Sequence { get; set; }
        /// <summary>
        /// 备注
        /// </summary>
        public string Remark { get; set; }

        public string TableName { get; set; }

        public string ColumnName { get; set; }
        public bool IsUnique { get; set; }

        public override DataBaseEntity Copy()
        {
            IndexEntity entity = new IndexEntity(Name) {Sequence = this.Sequence, Remark = this.Remark};

            Copy(entity);

            return entity;
        }
    }
    /// <summary>
    /// 索引描述
    /// </summary>
    [Serializable]
    public class IndexDescriptionEntity : DataBaseEntity
    {
        public IndexDescriptionEntity(string name)
            : base(name)
        {
            
        }
        /// <summary>
        /// 是否是唯一索引
        /// </summary>
        public bool IsUnique { get; set; }

        public string UniqueString {
            get
            {
                if (IsUnique)
                {
                    return "[唯一]";
                }
                return "";
            }
        }

        public string TableName { get; set; }

        public override DataBaseEntity Copy()
        {
            DescriptionEntity entity = new DescriptionEntity(Name);
            Copy(entity);
            if (this.ChildNodes.Count > 0)
            {
                foreach (DataBaseEntity db in this.ChildNodes.ToArray())
                {
                    DataBaseEntity baseEntity = db.Copy();
                    if (baseEntity != null)
                    {
                        entity.ChildNodes.Add(db.Copy());
                    }
                }
            }
            return entity;
        }
    }


    /// <summary>
    /// 关系实体
    /// </summary>
    [Serializable]
    public class RelationshipEntity : DataBaseEntity
    {
        public RelationshipEntity(string name):base(name)
        {
            ImageUrl = "/Images/Tree/foreignkey.png";
        }
        /// <summary>
        /// 外键列
        /// </summary>
        public string ColumnName { get; set; }
        /// <summary>
        /// 关系表
        /// </summary>
        public string RelationTableName { get; set; }
        /// <summary>
        /// 关系列
        /// </summary>
        public string RelationColumnName { get; set; }
        /// <summary>
        /// 是否级联删除
        /// </summary>
        public bool IsCascadingDelete { get; set; }
        /// <summary>
        /// 是否级联更新
        /// </summary>
        public bool IsCascadingUpdate { get; set; }
        /// <summary>
        /// 外键名称
        /// </summary>
        public string RefKeyName { get; set; }

        public string TableName { get; set; }

        public override DataBaseEntity Copy()
        {
            RelationshipEntity entity = new RelationshipEntity(Name)
                                            {
                                                ColumnName = this.ColumnName,
                                                RelationTableName = this.RelationTableName,
                                                RelationColumnName = this.RelationColumnName
                                            };
            Copy(entity);

            return entity;
        }
    }

    /// <summary>
    /// 视图
    /// </summary>
    [Serializable]
    [XmlInclude(typeof(ProcEntity))]
    public class ViewEntity : DataBaseEntity
    {
        public ViewEntity(string name):base(name)
        {
            ImageUrl = "/Images/Tree/view.png";
        }
        public string Content { get; set; }

        public override DataBaseEntity Copy()
        {
            ViewEntity entity = new ViewEntity(Name) {Content = this.Content};
            Copy(entity);
            if (this.ChildNodes.Count > 0)
            {
                foreach (DataBaseEntity db in this.ChildNodes.ToArray())
                {
                    DataBaseEntity baseEntity = db.Copy();
                    if (baseEntity != null)
                    {
                        entity.ChildNodes.Add(db.Copy());
                    }
                }
            }
            return entity;
        }
    }

    /// <summary>
    /// 存储过程
    /// </summary>
    [Serializable]
    public class ProcEntity : ViewEntity
    {
        public ProcEntity(string name):base(name)
        {
            ImageUrl = "/Images/Tree/proc.png";
        }
        public override DataBaseEntity Copy()
        {
            ProcEntity entity = new ProcEntity(Name);
            Copy(entity);
            if (this.ChildNodes.Count > 0)
            {
                foreach (DataBaseEntity db in this.ChildNodes)
                {
                    DataBaseEntity baseEntity = db.Copy();
                    if (baseEntity != null)
                    {
                        entity.ChildNodes.Add(db.Copy());
                    }
                }
            }
            return entity;
        }

    }

    /// <summary>
    /// 存储过程参数信息
    /// </summary>
    [Serializable]
    public class ProcParamEntity : FieldEntity
    {
        public ProcParamEntity(string name):base(name)
        {
            ImageUrl = "/Images/Tree/field.png";
        }
        public string Status { get; set; }
        public string ProcName { get; set; }

        public override DataBaseEntity Copy()
        {
            ProcParamEntity entity = new ProcParamEntity(Name);
            Copy(entity);
            entity.Status = this.Status;
            entity.Index = this.Index;
            return entity;
        }
    }

    /// <summary>
    /// 描述
    /// </summary>
     [Serializable]
    public class DescriptionEntity : DataBaseEntity
    {
        public DescriptionEntity(string name)
            : base(name)
        {
            //this.ChildNodes.Add(new DataBaseEntity("正在加载"));
        }
         public override DataBaseEntity Copy()
         {
             DescriptionEntity entity = new DescriptionEntity(Name);
             Copy(entity);
             if (this.ChildNodes.Count > 0)
             {
                 foreach (DataBaseEntity db in this.ChildNodes.ToArray())
                 {
                     DataBaseEntity baseEntity = db.Copy();
                     if (baseEntity != null)
                     {
                         entity.ChildNodes.Add(db.Copy());
                     }
                 }
             }
             return entity;
         }
     }

     [Serializable]
    public class TypeInfoEntity 
    {
        public string TypeName { get; set; }
        public int Length { get; set; }
        public int Scale { get; set; }
    }
}
